/// /////////////////////////////////////////////
// 单元名 : uc
// 作者 : Hawk
// 单元描述 :
// 日期 : 2023-09-15
/// /////////////////////////////////////////////

{$IFDEF FPC}
{$H+}
{$MODE DELPHI}
{$ENDIF}
program uc;
{$APPTYPE CONSOLE}

uses Windows, WinSock, unitMisc, unitClientUpdateMsgDefine, unitUpdateClientObj, unitMsgObj, unitCommonDataStruct,
  unitBlockMsgClient, unitCommCtrl, unitSvrMngCommon, unitClientUpdateObj, unitBlockSocket, unitErrCodeDef, unitObjBase;

{$R *.res}

{$IFDEF DEBUG}
const
  S_ROOTDOMAIN: array [0 .. 0] of AnsiString = ('homesvr');
{$ENDIF}

var
  ProductID: TID_OBJ;

type
  TMainProc = class
  private
    FRoot: TObjRoot;
    FBlockThread: TBlockSocketThread;
    FInitSession: TID_OBJ;
    FCurDomainIdx: integer;
    FExecTick: Longword;
    FUpdateComp: Boolean;

    procedure StartConn(uco: TUpdateClientObj);
    procedure UpdateProgress(Sender: TObject; Progress, Err: Longword);
    procedure Init;
    procedure Loop;
  end;

function CheckParam: Boolean;
var
  s: string;
begin
  if ParamCount > 1 then
    s := ParamStr(2)
  else if IsX64 then
    s := S_DLCNTX64
  else
    s := S_DLCNTX86;
  ProductID.FromStr(s);
  Result := not ProductID.IsEmpty;
end;

{ TMainProc }

procedure TMainProc.StartConn(uco: TUpdateClientObj);
var
  bmc: TBlockMsgClient;
begin
  bmc := TBlockMsgClient.Create;
  bmc.LocalIP := '0.0.0.0';
  bmc.RemoteIP := S_ROOTDOMAIN[FCurDomainIdx];
  bmc.RemotePort := 18521;
  uco.MSgClient := bmc;
  FBlockThread.AddBlockSocketObj(bmc);
  UpdateProgress(nil, UPDATEPROGRESS_CONNSVR, FCurDomainIdx);
end;

procedure TMainProc.UpdateProgress(Sender: TObject; Progress, Err: Longword);
var
  s: string;
begin
  case Progress of
    UPDATEPROGRESS_STARTUPDATE:
      s := '启动更新流程';
    UPDATEPROGRESS_CONNSVR:
      s := '连接到更新服务器:' + string(S_ROOTDOMAIN[Err]);
    UPDATEPROGRESS_FETCHUPDATEINFO:
      s := '已经连接，正在请求客户端文件版本信息';
    UPDATEPROGRESS_PROJECTNOTFOUND:
      begin
        s := '没有找到指定的项目';
        FUpdateComp := True;
      end;
    UPDATEPROGRESS_STARTDOWNLOADFILE:
      s := '已经检查完本地文件，正在下载文件';
    UPDATEPROGRESS_REPLACELOCALFILE:
      s := '已经完成文件下载，正在替换本地文件';
    UPDATEPROGRESS_UPDATECOMPLETE:
      begin
        s := '更新完成';
        FUpdateComp := True;
      end;
    UPDATEPROGRESS_NEEDRESTART:
      s := '需要重新启动程序';
    UPDATEPROGRESS_ACCESSDENYED:
      begin
        s := '连接到更新服务器失败 ' + ErrCodeToStr(Err);
        Inc(FCurDomainIdx);
        FUpdateComp := FCurDomainIdx > High(S_ROOTDOMAIN);
        if not FUpdateComp then
          StartConn(TUpdateClientObj(Sender));
      end;
  else
    s := '';
  end;
  if s <> '' then
    Writeln('更新客户端:', s);
  FExecTick := 0;
end;

procedure TMainProc.Init;
var
  cid: TCPUID;
  uco: TUpdateClientObj;
begin
  DbgPrint('Enter init;', []);
  cid := GetCPUID;
  DbgPrint('CPUID is %s', [BufToStr(cid, SizeOf(cid))]);
  Move(cid, FInitSession, SizeOf(FInitSession));
  FInitSession.IDDetail.SubID.IDBuf[6] := 0;
  FBlockThread := TBlockSocketThread.Create('Block thread');
  DbgPrint('TBlockSocketThread Created;', []);
  FRoot := TObjRoot.Create;
  uco := TUpdateClientObj.Create;
  uco.ProductID := ProductID;
  uco.ClientGUID := FInitSession;
  uco.OnUpdateProgress := UpdateProgress;
  FRoot.AddObj(uco);
  DbgPrint('UpdateObject Created(%s);', [uco.FullObjID.ToString]);
  UpdateProgress(nil, UPDATEPROGRESS_STARTUPDATE, 0);
  FRoot.SendSystemStartMsg(0);
  StartConn(uco);
  DbgPrint('Exit init;', []);
end;

procedure TMainProc.Loop;
begin
  while not FUpdateComp do
  begin
    Sleep(1000);
    Inc(FExecTick);
    if FExecTick > 20 then
    begin
      Writeln('更新客户端:超时退出');
      Break;
    end;
  end;
end;

begin
  InitWinSock;
  if CheckParam then
    with TMainProc.Create do
    begin
      Init;
      Loop;
      Free;
    end
  else
    Writeln('Usage: xxxx I-D83ADC2E189FDBA5AABBFB9521F7C6');

end.
